use std::{collections::HashMap, path::Path};

use serde::{Deserialize, Serialize};

pub fn add(left: usize, right: usize) -> usize {
    left + right
}

pub fn hash_password(password: &str) -> String {
    use sha2::Digest;
    let mut hasher = sha2::Sha256::new();
    hasher.update(password);
    let result = hasher.finalize();
    format!("{:x}", result)
}

pub fn save_users(users: HashMap<String, User>) {
    let users_path = Path::new("users.json");
    let users_json = serde_json::to_string(&users).unwrap();
    std::fs::write(users_path, users_json).unwrap();
}

pub fn read_line() -> String {
    let mut buf = String::new();
    std::io::stdin().read_line(&mut buf).expect("stdin error");
    buf.trim().to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LoginAction {
    Granted(LoginRole),
    Denied,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LoginRole {
    Admin,
    User,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct User {
    pub username: String,
    pub password: String,
    pub role: LoginRole,
}

impl User {
    pub fn new(username: &str, password: &str, role: LoginRole) -> User {
        User {
            username: username.to_lowercase(),
            password: password.to_string(),
            role,
        }
    }
}


// pub fn get_users() -> Vec<User> {
//      vec![
//         User::new("admin", "password", LoginRole::Admin),
//         User::new("user", "pass", LoginRole::User),
//     ]
// }

// hash map

pub fn get_default_users() -> HashMap<String, User> {
  
    let mut users = HashMap::new();
    users.insert("admin".to_string(), User::new("admin", "password", LoginRole::Admin));
    users.insert("user".to_string(), User::new("user", "pass", LoginRole::User));
    users
}

pub fn get_users() -> HashMap<String, User> {
    let users_path = Path::new("users.json");
    if users_path.exists() {
        let users_json = std::fs::read_to_string(users_path).unwrap();
        let users: HashMap<String, User> = serde_json::from_str(&users_json).unwrap();
        users
    } else {
        let users = get_default_users();
        let users_json = serde_json::to_string(&users).unwrap();
        std::fs::write(users_path, users_json).unwrap();
        users
    }
}


pub fn login(username: &str, password: &str) -> Option<LoginAction> {
  
    if username != "admin" && username != "user" {
        return None
    }

    let users = get_users();

    // if let Some(user) = users.iter().find(|user| user.username == username.to_lowercase()) {
    //     if user.password == password {
    //         return Some(LoginAction::Granted(user.role.clone()));
    //     } else {
    //         return Some(LoginAction::Denied);
    //     }
    // }
    // match (username, password) {
    //     ("admin", "password") => Some(LoginAction::Granted(LoginRole::Admin)),
    //     ("user", "pass") => Some(LoginAction::Granted(LoginRole::User)),
    //     _ => Some(LoginAction::Denied),
    // }


    match users.get(username) {
        Some(user) => {
            if user.password == password {
                Some(LoginAction::Granted(user.role.clone()))
            } else {
                Some(LoginAction::Denied)
            }
        },
        None => Some(LoginAction::Denied),
    }
        
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }
}
